package soul.web.resource;

import org.activiti.engine.*;
import org.activiti.engine.form.FormProperty;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.impl.form.StartFormDataImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import soul.utils.DateUtils;
import soul.web.vo.FormPagination;
import soul.web.vo.Response;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by admin on 2017/3/11.
 */
@Controller
@RequestMapping("/process")
public class SProcessResource {

    @Autowired
    private HistoryService historyService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private FormService formService;
    @Autowired
    private IdentityService identityService;


    /**
     * 获取启动流程需要的参数，用来渲染表单（请假时间，请假原因）
     */
    @PostMapping("start-process-data/{processDefinitionId}")
    @ResponseBody
    public Response findStartForm(@PathVariable("processDefinitionId") String processDefinitionId) throws Exception {
        Map<String, Object> result = new HashMap<String, Object>();
        StartFormDataImpl startFormData = (StartFormDataImpl) formService.getStartFormData(processDefinitionId);
        startFormData.setProcessDefinition(null);

        List<FormProperty> formProperties = startFormData.getFormProperties();

        return Response.ok(formProperties);
    }

    /**
     * 提交启动流程
     */
    @PostMapping(value = "start-process/{processDefinitionId}")
    @ResponseBody
    public Response startProcess(@PathVariable("processDefinitionId") String processDefinitionId,
                                                         @RequestBody Map<String, String> map) {
        try {
            identityService.setAuthenticatedUserId(map.get("apply_user_id"));
            formService.submitStartFormData(processDefinitionId, map);
        } finally {
            identityService.setAuthenticatedUserId(null);
        }
        return Response.ok();
    }


    //** 流程定义
    @RequestMapping("/list")
    @ResponseBody
    public Response selectProcess(@RequestBody FormPagination pagination) {
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().orderByDeploymentId().desc();
        List<ProcessDefinition> list = processDefinitionQuery.listPage(pagination.getPageNum() - 1, pagination.getPageSize());
        List<Map<String, Object>> vos = new ArrayList<>();
        list.forEach(processDefinition -> {
            HashMap<String, Object> vo = new HashMap<>();
            vo.put("processDefinitionId", processDefinition.getId());
            vo.put("processDefinitionName", processDefinition.getName() ==null? processDefinition.getKey():processDefinition.getName());
            vo.put("processDefinitionVersion", processDefinition.getVersion());
            vo.put("isSuspended", processDefinition.isSuspended());
            vo.put("deployId", processDefinition.getDeploymentId());
            vo.put("xml", processDefinition.getResourceName());
            vo.put("img", processDefinition.getDiagramResourceName());
            vos.add(vo);
        });
        return Response.ok(vos);
    }

    /**
     * 运行中的流程实例
     */
    @PostMapping("running/list")
    @ResponseBody
    public Response running(@RequestBody FormPagination pagination) {
        ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().active().orderByProcessInstanceId().desc();
        List<ProcessInstance> list = query.listPage(pagination.getPageNum() - 1, pagination.getPageSize());
        List<Map<String, Object>> vos = new ArrayList<>();
        list.forEach(processDefinition -> {
            HashMap<String, Object> vo = new HashMap<>();
            vo.put("processDefinitionId", processDefinition.getProcessDefinitionId());
            vo.put("processInstanceId", processDefinition.getProcessInstanceId());
            vo.put("processDefinitionName", processDefinition.getProcessDefinitionName());
            vo.put("isSuspended", processDefinition.isSuspended());
            vo.put("deployId", processDefinition.getDeploymentId());
            vos.add(vo);
        });
        return Response.ok(vos);
    }

    /**
     * 已结束的流程实例
     */
    @PostMapping("finished/list")
    @ResponseBody
    public Response finished(@RequestBody FormPagination pagination) {
        HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery().orderByProcessInstanceEndTime().desc().finished();
        List<HistoricProcessInstance> list = query.listPage(pagination.getPageNum() - 1, pagination.getPageSize());
        List<Map<String, Object>> vos = new ArrayList<>();
        list.forEach(historicProcessInstance -> {
            HashMap<String, Object> vo = new HashMap<>();
            vo.put("processDefinitionId",historicProcessInstance.getProcessDefinitionId());
            vo.put("startTime", DateUtils.formatDate(historicProcessInstance.getEndTime(),DateUtils.PATTERN_ONE));
            vo.put("endTime", DateUtils.formatDate(historicProcessInstance.getEndTime(),DateUtils.PATTERN_ONE));
            vo.put("instanceId", historicProcessInstance.getId());
            vos.add(vo);
        });
        return Response.ok(vos);
    }


    /**
     * 删除模型
     */
    @PostMapping("/delete/{deploymentId}")
    @ResponseBody
    public Response delete(@PathVariable("deploymentId") String deploymentId) {
        repositoryService.deleteDeployment(deploymentId, true);
//        repositoryService.deleteModel(modelId);
        return Response.ok();
    }

    /**
     * 展示流程图片或xml
     *
     * @param processDefinitionId 流程定义
     * @param resourceType        资源类型(xml|image)
     * @throws Exception
     */
    @RequestMapping(value = "/resource/read")
    public void loadByDeployment(@RequestParam("processDefinitionId") String processDefinitionId, @RequestParam("resourceType") String resourceType,
                                 HttpServletResponse response) throws Exception {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult();
        String resourceName = "";
        if (resourceType.equals("image")) {
            resourceName = processDefinition.getDiagramResourceName();
        } else if (resourceType.equals("xml")) {
            resourceName = processDefinition.getResourceName();
        }
        InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName);
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }

    /**
     * 挂起、激活流程实例
     */
    @RequestMapping(value = "processdefinition/update/{state}/{processDefinitionId}")
    @ResponseBody
    public Response updateState(@PathVariable("state") String state,
                                @PathVariable("processDefinitionId") String processDefinitionId) {
        if (state.equals("active")) {
            repositoryService.activateProcessDefinitionById(processDefinitionId, true, null);
        } else if (state.equals("suspend")) {
            repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null);
        }
        return Response.ok();
    }
}
